package org.design.singleton;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

/**
 * 一个非常简单的单例模式 
 * 1. 私有静态的一个自己 
 * 2. 构造函数私有，这样的话，就不能随意new实例了 
 * 3. 用一个静态方法获得一个实例
 * 4. 针对反射和序列化，我们需要做点额外的事情
 * 5. 尝试用sync来做同步
 * 
 * @author chenxianpeng
 *
 */
public class SimpleSingleton4 implements Serializable {
	private static SimpleSingleton4 _instance = null;
	private static final SimpleSingleton4 _instance3 = new SimpleSingleton4();
	
	private static class innerFactory {
		//延迟加载
		private static SimpleSingleton4 _instance2 = new SimpleSingleton4();
	}

	private SimpleSingleton4() {
		// TODO Auto-generated constructor stub
		// 防止反射获取多个对象的漏洞 
		// 这种方式只能防止已经执行过getInstance时的代码。
		//因为没有执行getInstance时，_instance永远是null的。
        if (null != _instance) {  
            throw new RuntimeException();  
        }  
	}

	// case 1 synchronized加在方法上,可行，就是性能上有损耗
	public static synchronized SimpleSingleton4 getInstanceSync1() {
		if (_instance == null) {
			_instance = new SimpleSingleton4();
		}
		return _instance;
	}
	//case 2, synchronized 加在方法里面
	//看起来性能是提上来了，其实是有问题的。
	public static SimpleSingleton4 getInstanceSync2() {
		if (_instance == null) {
//			synchronized(_instance) {//对null的对象做同步锁，直接挂了
			synchronized(SimpleSingleton4.class) {
				if(_instance == null) {
					_instance = new SimpleSingleton4();
				}
			}
		}
		return _instance;
	}
	
	//case 3使用内部私有静态类
	public static SimpleSingleton4 getInstanceSync3() {
		return innerFactory._instance2;
	}
	
	//case 4 直接使用静态对象
	public static SimpleSingleton4 getInstanceSync4() {
		return _instance3;
	}
	
	
	
	// 防止反序列化获取多个对象的漏洞。  
    // 无论是实现Serializable接口，或是Externalizable接口，当从I/O流中读取对象时，readResolve()方法都会被调用到。  
    // 实际上就是用readResolve()中返回的对象直接替换在反序列化过程中创建的对象。  
    private Object readResolve() throws ObjectStreamException {    
        return _instance;  
    }  

	public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, IOException, InterruptedException {
		//如果在多线程环境下，会发生什么事情
//		runcase(MyThread41.class);//运行多次，平均在110＋左右
//		runcase(MyThread42.class);//在我们这样的情况下，提升不多
//		runcase(MyThread43.class);//好一些
		runcase(MyThread44.class);//好很多
	}
	
	private  static <T> void  runcase(Class<T> clz) throws InterruptedException, InstantiationException, IllegalAccessException {
		int num = 1000;
		List<T> t = new ArrayList<T>();
		for (int i = 0; i < num; i++) {
			t.add(clz.newInstance());
		}
		long start = System.currentTimeMillis();
		for(int i = 0; i < num; i++) {
			((Thread)(t.get(i))).start();
		}
		for(int i =0 ; i< num; i++) {
			((Thread)(t.get(i))).join();
		}
		long end = System.currentTimeMillis();
		System.out.println("case use " + clz.getName() + " " + (end - start));
	}

}

class MyThread41 extends Thread {
	public void run() {
		SimpleSingleton4 ss = SimpleSingleton4.getInstanceSync1();
		System.out.println("ss=" + ss);
	}
}

class MyThread42 extends Thread {
	public void run() {
		SimpleSingleton4 ss = SimpleSingleton4.getInstanceSync2();
		System.out.println("ss=" + ss);
	}
}

class MyThread43 extends Thread {
	public void run() {
		SimpleSingleton4 ss = SimpleSingleton4.getInstanceSync3();
		System.out.println("ss=" + ss);
	}
}

class MyThread44 extends Thread {
	public void run() {
		SimpleSingleton4 ss = SimpleSingleton4.getInstanceSync4();
		System.out.println("ss=" + ss);
	}
}
